package com.pointi.emoEngine;

import java.util.ArrayList;

import com.pointi.emoTools.EmotionPacket;

public class DSP_Feature
{
	public int W_length = EmotionPacket.frameSize ;	// window length, r(k) order -> Autocorrelation..
	public int fft_size = 256 ;

	// ____________________________________________________________________________________________________

	public DSP_Feature () { }

	// ____________________________________________________________________________________________________
	// Rectangular windowing

	public void FrameProcessing(short [] pData, double [] pX)
	{
		pX[0] = (double)pData[0] ;
		for (int m = 1 ; m < W_length ; m++) { pX[m] = (double)pData[m] ; }
	}

	// ____________________________________________________________________________________________________
	// Calculate Auto-Correlation
	//		-	double *pX		: windowed data
	//		-	double *pRxx	: autocorrelation

	public void CalcAuto(double [] pX, double [] pRxx)
	{
		int k ;
		int n ;
		for (k = 0 ; k < W_length ; k++)
		{
			pRxx[k] = 0.0 ;
			for (n = 0 ; n < W_length - k ; n++) { pRxx[k] = pRxx[k] + pX[n] * pX[n + k] ; }
			pRxx[k] = pRxx[k] / W_length ;
		}
	}

	// ____________________________________________________________________________________________________
	//
	//		Energy0	: Short-time Energy	(r(0))
	//		Pitch0	: Fundamental Frequency
	//		MFCC0	: Mel-Frequency Cepstral Coefficients (MFCCs)
	//		x		: Hamming Windowed Data
	//		Rxx		: Autocorrelation

	public void ExtractFeature(short [] mSAMPLE, VoicedFrame voicedFrame, int CNT, ArrayList<int[]> inIndex, ArrayList<double[]> inFeature, int mode)
	{
		double Energy0 ;
		double Pitch0 ;
		double [] MFCC0 ;
		double [] x = new double [W_length] ;
		double [] Rxx = new double [W_length] ;
		double [] ceps = new double [12] ;
		double [] spectrum = new double [fft_size + 1] ;
		double [] mFeature = new double [13] ; // for Voice Engine

		Energy0 = 0 ;
		Pitch0 = 0 ;
		MFCC0 = new double[12] ;

		// ____________________________________________________________________________________________________
		//	01. Frame Processing
		//	02. Autocorrelation Analysis
		//	03. Pre-emphasis Factor ..  Voiced, Unvoiced ..

		DSP_FFT dsp_fft = new DSP_FFT();
		DSP_Pitch dsp_pitch = new DSP_Pitch();
		DSP_MFCC dsp_mfcc = new DSP_MFCC();

		FrameProcessing(mSAMPLE, x) ; // 01
		CalcAuto(x, Rxx) ; // 02
		Energy0 = 10 * Math.log10(Rxx[0]) ;
		double mu = Rxx[1] / Rxx[0] ; // 03
		if (Energy0 > 40 && mu > 0.5)
		{
			dsp_fft.FFT(x, W_length, fft_size, spectrum) ;
			Pitch0 = dsp_pitch.GetPitch(spectrum) ;	
			dsp_mfcc.GetMFCC(spectrum, ceps) ;
			mFeature[0] = 0 ; // for Voice Engine
			for (int m = 0 ; m < 12 ; m++)
			{
				MFCC0[m] = ceps[m] ;
				// Select Feature | 2014.04.09 |
				{
					switch((m+1)) 
					{
					case 6:
						mFeature[m+1] = ceps[m] ;
						break ;
					case 7:
						mFeature[m+1] = ceps[m] ;
						break ;
					case 8:
						mFeature[m+1] = ceps[m] ;
						break ;
					case 9:
						mFeature[m+1] = ceps[m] ;
						break ;
					default :
						// mFeature[m+1] = ceps[m] ; // for TEST | Store All Feature
						mFeature[m+1] = 0 ;
						break ;
					}
				}
			}
			// Store Voice Feature | 2014.04.09 |
			{
				int [] mIndex = new int[2] ;
				mIndex[0] = CNT ;
				if (Pitch0 != 0)
				{
					mIndex[1] = 1 ;
					inIndex.add(mIndex) ;
					inFeature.add(mFeature) ;
				}
				else
				{
					mIndex[1] = 0 ;
					inIndex.add(mIndex) ;
				}
			}
		}
		else
		{
			Pitch0 = 0.0 ;
			for (int m = 0 ; m < 12 ; m++) { MFCC0[m] = 0.0 ; }	
			// Store Unvoice Feature | 2014.04.09 |
			{
				int [] mIndex = new int[2] ;
				mIndex[0] = CNT ;
				mIndex[1] = 0 ;
				inIndex.add(mIndex) ;
			}
		}
		
		if (mode != 1)
			voicedFrame.addVoicedFrame(Pitch0, Energy0, MFCC0) ; // for Emotion Engine
	}
}
